package com.python.listener.core;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.python.listener.entity.ReturnEntity;
import com.squareup.javapoet.*;
import org.springframework.stereotype.Service;

import javax.lang.model.element.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 文件生成
 *
 * @author zt
 */
public class GeneFile {

    /**
     * 生成接口文件
     */
    public static JavaFile geneInterface(List<JSONObject> funcInfos, String interfacePath) {
        List<MethodSpec> allFuncList = new ArrayList<>();
        for (JSONObject funcInfo : funcInfos) {
            JSONArray paramArray = funcInfo.getJSONArray("params");
            List<ParameterSpec> parameterSpecs = paramArray.stream().map(v -> ParameterSpec.builder(Object.class, String.valueOf(v)).build()).collect(Collectors.toList());
            MethodSpec methodSpec = MethodSpec.methodBuilder(funcInfo.getString("module_name"))
                    .addModifiers(Modifier.PUBLIC)
                    .addModifiers(Modifier.ABSTRACT)
                    .addParameters(parameterSpecs)
                    .addJavadoc(funcInfo.getString("note"))
                    .returns(ReturnEntity.class)
                    .build();
            allFuncList.add(methodSpec);
        }
        TypeSpec typeSpec = TypeSpec.interfaceBuilder("IPyRpcService")
                .addModifiers(Modifier.PUBLIC)
                .addMethods(allFuncList)
                .build();
        return JavaFile.builder(interfacePath, typeSpec)
                .addFileComment(" This codes are generated automatically. Do not modify! ")
                .build();
    }

    /**
     * 生成实现类文件
     */
    public static JavaFile geneImpl(List<JSONObject> funcInfos, String interfacePath, String addressIp, int port) {
        List<MethodSpec> allFuncList = new ArrayList<>();
        for (JSONObject funcInfo : funcInfos) {
            String moduleName = funcInfo.getString("module_name");
            JSONArray paramArr = funcInfo.getJSONArray("params");
            List<ParameterSpec> parameterSpecs = paramArr.stream().map(v -> ParameterSpec.builder(Object.class, String.valueOf(v)).build()).collect(Collectors.toList());
            MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder(moduleName)
                    .addModifiers(Modifier.PUBLIC)
                    .addAnnotation(Override.class)
                    .addParameters(parameterSpecs)
                    .returns(ReturnEntity.class);
            getImplCode(addressIp, port, moduleName, paramArr, methodSpecBuilder);
            allFuncList.add(methodSpecBuilder.build());
        }
        TypeSpec typeSpec = TypeSpec.classBuilder("PyRpcServiceImpl")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Service.class)
                .addSuperinterface(ClassName.get(interfacePath, "IPyRpcService"))
                .addMethods(allFuncList)

                .build();
        return JavaFile.builder(interfacePath, typeSpec)
                .addFileComment(" This codes are generated automatically. Do not modify! ")
                .build();
    }

    /**
     * 生成代码体
     */
    private static void getImplCode(String addressIp, int port, String moduleName, JSONArray paramArr, MethodSpec.Builder builder) {
        ClassName jsonClass = ClassName.get("com.alibaba.fastjson", "JSON");
        ClassName socketClass = ClassName.get("com.python.listener.core", "ChannelSocketWrite");
        ClassName requestClass = ClassName.get("com.python.listener.entity", "RequestEntity");
        ClassName returnClass = ClassName.get("com.python.listener.entity", "ReturnEntity");
        ClassName hashMapClass = ClassName.get("java.util", "HashMap");
        builder.addStatement("String addressIp = \"" + addressIp + "\"")
                .addStatement("int port = " + port)
                .addStatement("$T.init(addressIp, port)", socketClass)
                .addStatement("$T requestEntity = new RequestEntity()", requestClass)
                .addStatement("requestEntity.setFuncName(\"" + moduleName + "\")")
                .addStatement("$T<String, Object> paramMap = new HashMap<>()", hashMapClass);
        for (Object o : paramArr) {
            String p = String.valueOf(o);
            builder.addStatement("paramMap.put(\"" + p + "\", " + p + ")");
        }
        builder.addStatement("requestEntity.setParams(paramMap)")
                .addStatement("String result = ChannelSocketWrite.call(JSON.toJSONString(requestEntity))")
                .addStatement("result = result.replace(\"'\", \"\\\"\").replace(\"(\", \"[\").replace(\")\", \"]\")")
                .addStatement("return $T.parseObject(result, $T.class)", jsonClass, returnClass);
    }
}
